import ctypes
import os
import shutil
import subprocess

from PyQt6.QtCore import Qt, QTimer, QUrl
from PyQt6.QtGui import QDesktopServices, QIcon
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QTabWidget, QPushButton, QLabel, \
    QHBoxLayout, QPlainTextEdit

from .GetPushClipper import GetPushClipper
from .ReportBug import ReportBug
from ._ReadYaml import ReadYaml


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        # set application icon
        myappid = 'mycompany.myproduct.subproduct.version'
        ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

        self.clear_folder_button = None
        self.initUI()
        self.current_dir = os.getcwd()

    def _center_window(self):
        # 获取当前屏幕的几何信息
        screen = self.screen().availableGeometry()
        # 获取窗口的几何信息
        size = self.geometry()
        # 计算窗口应该移动到的位置，使其居中
        x = (screen.width() - size.width()) // 2
        y = (screen.height() - size.height()) // 2
        # 移动窗口到计算的位置
        self.move(x, y)

    def initUI(self):
        self._get_log_init()

        self.setWindowTitle("Phone Tools")

        # self.set Geometry(1050, 200, 300, 400)
        self.setMaximumSize(280, 400)
        self.setFixedSize(280, 400)
        self._center_window()
        self.icon_path = os.path.join(os.getcwd(), 'platform-tools', 'icon.ico')
        self.setWindowIcon(QIcon(self.icon_path))

        # 创建主布局
        layout = QVBoxLayout()
        # 创建页签部件
        tab_widget = QTabWidget()
        # 创建第一个页签
        tab1 = QWidget()
        tab2 = QWidget()
        # 页签状态说明
        self.label1 = QLabel("")
        self.label2 = QLabel("")

        # 设置自动换行
        self.label1.setWordWrap(True)
        self.label2.setWordWrap(True)

        # 输入框只支持单行输入
        # self.textbox = QLineEdit()
        # 富文本框，支持最多种类
        # self.textbox = QTextEdit()
        # 支持换行的文本输入框
        self.textbox = QPlainTextEdit()
        self.textbox.setFixedHeight(50)

        # 页签1按钮
        self.connect_button = QPushButton("连接手机", self)
        self.connect_button.setGeometry(0, 50, 100, 30)
        self.connect_button.clicked.connect(self.connect_phone)

        self.open_folder_button = QPushButton("打开文件夹", self)
        self.open_folder_button.setGeometry(0, 50, 100, 30)
        self.open_folder_button.clicked.connect(self.open_folder)

        self.take_screenshot_button = QPushButton("截图", self)
        self.take_screenshot_button.setGeometry(0, 50, 100, 30)
        self.take_screenshot_button.clicked.connect(self.take_screenshot)

        self.get_latest_video_button = QPushButton("获取最新视频", self)
        self.get_latest_video_button.setGeometry(0, 50, 100, 30)
        self.get_latest_video_button.clicked.connect(self.get_latest_video)

        self.start_stop_log_button = QPushButton("实时获取log", self)
        self.start_stop_log_button.setGeometry(0, 50, 100, 30)
        self.start_stop_log_button.clicked.connect(self.start_stop_log)

        self.pull_user_set_dir_button = QPushButton("拉取目录", self)
        self.pull_user_set_dir_button.setGeometry(0, 50, 100, 30)
        self.pull_user_set_dir_button.clicked.connect(self.pull_user_set_dir)

        self.get_clipboard_button = QPushButton("获取手机粘贴板", self)
        self.get_clipboard_button.setGeometry(0, 50, 100, 30)
        self.get_clipboard_button.clicked.connect(self.get_clipboard)

        self.push_clipboard_button = QPushButton("推送文本到手机", self)
        self.push_clipboard_button.setGeometry(0, 50, 100, 30)
        self.push_clipboard_button.clicked.connect(self.push_clipboard)

        # 页签2按钮
        self.open_url_button = QPushButton("使用说明", self)
        self.open_url_button.setGeometry(0, 50, 100, 30)
        self.open_url_button.clicked.connect(self.open_url)

        self.clear_folder_button = QPushButton("清理文件夹", self)
        self.clear_folder_button.setGeometry(0, 50, 100, 30)
        self.clear_folder_button.clicked.connect(self.clear_folder)

        self.bug_report_button = QPushButton("提交bug", self)
        self.bug_report_button.setGeometry(0, 50, 100, 30)
        self.bug_report_button.clicked.connect(self.bug_report)

        self.fix_bug_button = QPushButton("关闭bug", self)
        self.fix_bug_button.setGeometry(0, 50, 100, 30)
        self.fix_bug_button.clicked.connect(self.fix_bug)

        # 页签1-布局
        tab1_layout = QVBoxLayout()
        # 嵌套水平布局
        hbox1 = QHBoxLayout()
        tab1_layout.addLayout(hbox1)
        hbox2 = QHBoxLayout()
        tab1_layout.addLayout(hbox2)
        hbox3 = QHBoxLayout()
        tab1_layout.addLayout(hbox3)
        hbox4 = QHBoxLayout()
        tab1_layout.addLayout(hbox4)
        hbox5 = QHBoxLayout()
        tab1_layout.addLayout(hbox5)
        hbox6 = QHBoxLayout()
        tab1_layout.addLayout(hbox6)
        hbox7 = QHBoxLayout()
        tab1_layout.addLayout(hbox7)
        hbox8 = QHBoxLayout()
        tab1_layout.addLayout(hbox8)

        # 页签2-布局
        tab2_layout = QVBoxLayout()
        vbox1 = QHBoxLayout()
        tab2_layout.addLayout(vbox1)
        vbox2 = QHBoxLayout()
        tab2_layout.addLayout(vbox2)
        vbox3 = QHBoxLayout()
        tab2_layout.addLayout(vbox3)

        # 页签1添加按钮
        hbox1.addWidget(self.open_folder_button)
        hbox2.addWidget(self.connect_button)
        hbox3.addWidget(self.take_screenshot_button)
        hbox4.addWidget(self.get_latest_video_button)
        hbox5.addWidget(self.start_stop_log_button)
        hbox6.addWidget(self.pull_user_set_dir_button)
        hbox7.addWidget(self.get_clipboard_button)
        hbox7.addWidget(self.push_clipboard_button)
        hbox8.addWidget(self.textbox)

        # 页签2添加按钮
        vbox1.addWidget(self.open_url_button)
        vbox2.addWidget(self.clear_folder_button)
        vbox3.addWidget(self.bug_report_button)
        vbox3.addWidget(self.fix_bug_button)

        # 底部说明
        tab1_layout.addWidget(self.label1, alignment=Qt.AlignmentFlag.AlignBottom)
        tab2_layout.addWidget(self.label2, alignment=Qt.AlignmentFlag.AlignBottom)
        tab1.setLayout(tab1_layout)
        tab2.setLayout(tab2_layout)

        # 页签名字
        tab_widget.addTab(tab1, "功能")
        tab_widget.addTab(tab2, "其他")

        layout.addWidget(tab_widget)
        self.setLayout(layout)

    def label1_text(self, text, msg=''):
        # 设置 QLabel 的文本，并根据每37个字符进行换行
        print("log -> label1_text: ", text)
        # formatted_text = "\n".join(text[i:i + 33] for i in range(0, len(text + msg), 33))
        formatted_text = "".join(text + msg)
        self.label1.setText(formatted_text)

    def check_phone_connection(func):
        def wrapper(self):
            try:
                # 执行 adb devices 命令并捕获输出
                output = subprocess.check_output(['adb', 'devices', ], universal_newlines=True,
                                                 creationflags=subprocess.CREATE_NO_WINDOW)
                if len([line.split('\t')[0] for line in output.strip().splitlines()[1:]]) > 1:
                    self.label1_text("连接设备数量 > 1")
                    self.phone_connected = False
                    return
                # 解析输出，获取设备信息列表
                device_info = output.strip().split('\n')[1:]
                for device in device_info:
                    serial, status = device.split('\t')
                    # 判断设备状态是否为 "device"
                    if status == "device":
                        self.label1_text(f"Phone is connected:\n{serial}")
                        self.phone_connected = True
                        break
                else:
                    self.label1_text("更换数据线,确认USB偏好设置为:文件传输")
                    self.phone_connected = False
            except Exception as e:
                # 如果命令执行失败，则说明 adb 未安装或设备未连接
                self.label1_text("手机未连接,或连接状态不正确,查看手机状态2")
                self.phone_connected = False
            func(self)  # 执行原始函数

        return wrapper

    @check_phone_connection
    def connect_phone(self):
        pass
        # 解决各种连接问题

    def _sub_run_commands(self, commands=(), index=None):
        """
        连续执行n个命令
        @param commands: command list
        @param index: 控制list中哪些命令的执行结果显示在控制区中
        @return:
        """
        report_text = ""
        for i, command in enumerate(commands):
            process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                       creationflags=subprocess.CREATE_NO_WINDOW)
            output, error = process.communicate()
            if i == index:
                report_text += output.decode("utf-8") + "\n"
            if process.returncode != 0:
                self.label1_text(command, error.decode())
        self.label1_text("screenshot success:\n" + report_text)

    @check_phone_connection
    def take_screenshot(self):
        # 截图
        if not self.phone_connected: return
        commands = ("adb shell screencap /sdcard/screenshot.png",
                    "adb pull /sdcard/screenshot.png {0}".format(self.current_dir),
                    "start {0}\screenshot.png".format(self.current_dir),
                    "adb shell rm /sdcard/screenshot.png"
                    # f'start "" "{self.current_dir}\\screenshot.png"'
                    )
        self._sub_run_commands(commands, 1)

    def open_url(self):
        # 使用说明
        url = QUrl("https://docs.qq.com/doc/p/fbc6c34b104654ac414b00f6f3e15504a5009cda")
        QDesktopServices.openUrl(url)

    def open_folder(self):
        # 打开软件文件夹
        QDesktopServices.openUrl(QUrl.fromLocalFile(self.current_dir))

    def bug_report(self):
        # 提交bug
        ReportBug().report_bug()

    def fix_bug(self):
        # 关闭bug
        ReportBug().fix_bug()

    def _video_path_manager(self):
        """
        处理从config.yaml - video_paths 中获取的路径
        @return: 含有空格的路径中添加反斜杠，不含有的保持原样
        """
        new_video_paths = {}
        video_paths = ReadYaml.__call__().get("video_paths", [])
        if not video_paths:
            self.label1_text("Please set config.yaml -> video_paths")
            return
        for android_path in video_paths:
            # 判断路径中是否有空格
            if ' ' in android_path:
                # 如果有空格，处理路径
                parts = android_path.split('/')
                last_folder = parts[-1]
                new_last_folder = last_folder.replace(" ", "\ ")
                new_android_path = '/'.join(parts[:-1] + [f'{new_last_folder}'])
                new_video_paths.update({android_path: new_android_path})
            else:
                new_video_paths.update({android_path: android_path})
        print("new_video_paths: ", new_video_paths)
        return new_video_paths

    def is_video_file(self, filename):
        """
        判断filename是不是视频
        @return: true false
        """
        video_extensions = ['.mp4', '.avi', '.mov', '.mkv']  # 可能的视频文件扩展名列表
        return any(filename.lower().endswith(ext) for ext in video_extensions)

    @check_phone_connection
    def get_latest_video(self):
        """
        处理从yaml读取的路径，ls和pull使用不同的路径操作
        拉去最后一个视频
        @return:
        """
        video_paths = self._video_path_manager()
        print("video_paths", video_paths)
        if not self.phone_connected: return
        video_exist = False
        if video_paths:
            for android_path, new_android_path in video_paths.items():
                command = f"adb shell ls {new_android_path}"
                # 获取文件夹内的文件列表
                re_list = subprocess.run(command, shell=True, capture_output=True, text=True,
                                         creationflags=subprocess.CREATE_NO_WINDOW).stdout.splitlines()
                for filename in re_list:
                    # 如果这个文件是视频,就排序拉取最后一个视频
                    if self.is_video_file(filename):
                        output = subprocess.run(["adb", "shell", "ls", "-t", new_android_path], capture_output=True,
                                                text=True, creationflags=subprocess.CREATE_NO_WINDOW)
                        latest_video = output.stdout.splitlines()[0]
                        command = f'adb pull "{android_path}/{latest_video}" {self.current_dir}'
                        # print("android_path:", android_path)
                        # print("Latest_Video:", filename)
                        # print("command", command)
                        result = subprocess.run(command, shell=True, capture_output=True, text=True,
                                                creationflags=subprocess.CREATE_NO_WINDOW)
                        self.label1_text("pulled video success:\n" + result.stdout)
                        video_exist = True
                        break
        if not video_exist:
            self.label1_text("video path not found, please set config.yaml -> video_paths")

    # -------------------------------获取log
    def _get_log_init(self):
        self.adb_process = None
        self.log_running = False
        self.log_data = ""
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.read_log)

    def closeEvent(self, event):
        self.stop_log()
        event.accept()

    @check_phone_connection
    def start_stop_log(self):
        if not self.phone_connected: return
        if not self.log_running:
            self.start_stop_log_button.setText("停止获取")
            self.start_log()
        else:
            self.start_stop_log_button.setText("实时获取log")
            self.stop_log()

    def start_log(self):
        try:
            subprocess.run(["adb", "logcat", "-c"], check=True, creationflags=subprocess.CREATE_NO_WINDOW)
            self.adb_process = subprocess.Popen(['adb', 'logcat'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                                text=True, creationflags=subprocess.CREATE_NO_WINDOW)
            self.log_running = True
            self.timer.start(100)  # Start timer
        except Exception as e:
            self.label1_text(e)

    def stop_log(self):
        if self.adb_process:
            self.adb_process.terminate()
            self.adb_process = None
            self.log_running = False
            self.timer.stop()  # Stop timer
            self.save_log()  # Save log when stopping

    def read_log(self):
        if self.adb_process:
            output = self.adb_process.stdout.readline()
            self.label1_text(output.strip())
            self.log_data += output
            # Print log to console

    def save_log(self):
        if self.log_data:
            try:
                with open("adb_log.txt", "w") as file:
                    file.write(self.log_data)
                    self.label1_text("log saved successfully! -> adb_log.txt")
            except Exception as e:
                self.label1_text("Error", f"Failed to save log: {e}")

    # 获取指定目录的log
    @check_phone_connection
    def pull_user_set_dir(self):
        if not self.phone_connected: return
        user_set_dir = ReadYaml.__call__().get("user_set_dir", [])
        if not user_set_dir:
            self.label1_text("Please set config.yaml -> user_set_dir")
            return
        # Execute adb command to pull directory
        try:
            for dir in user_set_dir:
                subprocess.run(["adb", "pull", dir], check=True, creationflags=subprocess.CREATE_NO_WINDOW)
                self.label1_text("Directory pulled successfully!")
        except subprocess.CalledProcessError as e:
            self.label1_text("Error pulling directory: " + str(e))

    # 获取手机粘贴板信息
    @check_phone_connection
    def get_clipboard(self):
        if not self.phone_connected: return
        GetPushClipper().get_android_text(self.label1_text)

    # 推送信息到手机粘贴板
    @check_phone_connection
    def push_clipboard(self):
        if not self.phone_connected: return
        GetPushClipper().push_PC_text(self.textbox, self.label1_text)

    def clear_folder(self):
        """
        清理文件夹
        @return:
        """
        # 要删除的文件后缀列表
        extensions = ['.png', '.mp4', '.txt', 'spec']
        # 用户拉取的文件夹
        user_set_dir = ReadYaml.__call__().get("user_set_dir", [])
        # 打包文件夹
        build_dir = ['build', 'dist']
        try:
            if not user_set_dir:
                self.label2.setText("not found config.yaml -> user_set_dir")
                return
            for path in user_set_dir:
                last_folder = path.split('/')[-1]
                user_dir = os.path.join(self.current_dir, last_folder)
                if os.path.exists(user_dir):
                    shutil.rmtree(user_dir)
                else:
                    print("Could not find user_set_dir", user_dir)
            for dir in build_dir:
                _dir = os.path.join(self.current_dir, dir)
                if os.path.exists(_dir):
                    shutil.rmtree(_dir)
                else:
                    print("Could not find user_set_dir", _dir)
            # 遍历文件夹中的所有文件
            for file in os.listdir(self.current_dir):
                # 检查文件后缀是否在指定的后缀列表中
                for extension in extensions:
                    if file.endswith(extension):
                        file_path = os.path.join(self.current_dir, file)
                        # 删除文件
                        os.remove(file_path)
            self.label2.setText("clear folder done")
        except Exception as e:
            print(e)
            self.label2.setText(f"{e}")
